/**
 * 
 */
package com.vivid.dynamics.oknow.test.dao;

import java.io.Serializable;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.vivid.dynamics.junit.impl.SpringHibernateSupportJUnitTemplate;
import com.vivid.dynamics.oknow.config.spring.Constants;
import com.vivid.dynamics.oknow.dao.IUserDAO;
import com.vivid.dynamics.oknow.dao.IUserThemeDAO;
import com.vivid.dynamics.oknow.model.User;
import com.vivid.dynamics.oknow.model.UserTheme;

/**
 *
 * @author jason
 * created at:: Aug 8, 2011 4:22:30 PM
 */
public class UserThemeTestCase extends SpringHibernateSupportJUnitTemplate {
	/**
	 * IUserDAO, check the config under config/spring-config.xml
	 */
	private @Autowired IUserDAO userDAO;
	/**
	 * IUserThemeDAO, check the config under config/spring-config.xml
	 */
	private @Autowired IUserThemeDAO userThemeDAO;
	
	/**
	 * ctor.
	 */
	public UserThemeTestCase() {
		super(UserThemeTestCase.class, true);
	}
	
	User userA=null;
	User userB=null;
	Serializable userAKey=null;
	Serializable userBKey=null;
	
	/**
	 * get a valid UserTheme (eg. the default UserTheme -- which is a MUST valid entry)
	 * 
	 * @author jason
	 * created at:: Aug 8, 2011  4:35:59 PM
	 */
	@Test
	public void doTest001() {
		UserTheme aUTheme001=null;
		
		this.sb.append("\r\n************************************************\r\n").
		    append("*\tstart {UserThemeTestCase.doTest001}\t*\r\n").
			append("************************************************\r\n\r\n");
		
		try {
			/*
			 * 1) create User
			 */
			userA=new User("userA", "def", false, "hire", "a@abcAA.com", null);
			userB=new User("userB", "def", false, "hire", "a@abcBB.com", null);
			
			this.userAKey=this.userDAO.newUser(userA);
			this.userBKey=this.userDAO.newUser(userB);
			
			this.sb.append("get the User(s) on class Level~:: \r\n\t").
				append(this.userA).append("\r\n\t").
				append(this.userB).append("\r\n\r\n");
			
			aUTheme001=this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue());
			Assert.assertNotNull("1a) Default UserTheme should be AVAILABLE~~~", aUTheme001);
			this.sb.append(aUTheme001).append("\r\n\r\n");
			
			/*
			 * 1) delete the User
			 */
			if (this.userA!=null) this.userDAO.deleteUser(userA);
			if (this.userB!=null) this.userDAO.deleteUser(userB);
			this.userAKey=null;
			this.userBKey=null;
			
			this.tx.flush();
			
		} catch(RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}
	}
	
	/**
	 * add a new User and a new UserTheme (ordering of creation is UserTheme first, then User); associate them together
	 * 
	 * @author jason
	 * created at:: Aug 8, 2011  4:45:04 PM
	 */
	@Test
	public void doTest002() {
		UserTheme aUTheme001=null;
		Serializable aKey001=null;
		User aUsr001=null;
		User aUsr002=null;
		
		this.sb.append("\r\n************************************************\r\n").
		    append("*\tstart {UserThemeTestCase.doTest002}\t*\r\n").
			append("************************************************\r\n\r\n");
		
		try {
			/*
			 * 1) create User
			 */
			userA=new User("userA", "def", false, "hire", "a@abcAA.com", null);
			userB=new User("userB", "def", false, "hire", "a@abcBB.com", null);
			
			this.userAKey=this.userDAO.newUser(userA);
			this.userBKey=this.userDAO.newUser(userB);
			
			this.sb.append("2a) add a new User and a new UserTheme (ordering of creation is UserTheme first, then User); associate them together::\r\n\tCreating a new UserTheme::");
			aUTheme001=new UserTheme("themeDummy001", "dummy theme - to be deleted", "/tmp/template", null);
			aKey001=this.userThemeDAO.newUserTheme(aUTheme001);
			Assert.assertNotNull("2a) should be able to create a UserTheme~", aKey001);
		
			// re-query
			aUTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aKey001);
			Assert.assertNotNull("2a) re-query should return the JUST created UserTheme~", aUTheme001);
			Assert.assertEquals("2a) the Keys after re-query should be the same~", ((Integer) aKey001).intValue(), aUTheme001.getId());
			this.sb.append(aKey001).append("\r\n\r\n");
			
			this.sb.append("2b) creating new Users to associate with the JUST created userTheme ::\r\n\tCreating new Users::");
			/*
			 * should not directly manipulate the associations directly
			 * 
			 * use association methods instead of direct manipulations~~~
			 */
			//aUsr001.setUserTheme(aUTheme002);
			//aUsr002.setUserTheme(aUTheme002);
			aUTheme001.addUser(this.userA);
			aUTheme001.addUser(this.userB);
			/*
			 * update the UserTheme table...
			 */
			this.userThemeDAO.updateUserTheme(aUTheme001);
			
			// re-query
			aUsr001=this.userDAO.getUserByKey((Integer) this.userAKey);
			aUsr002=this.userDAO.getUserByKey((Integer) this.userBKey);
			Assert.assertTrue("2b) Should be...non \"0\"", aUsr001.getId()>0);
			Assert.assertTrue("2b) Should be...non \"0\"", aUsr002.getId()>0);
			/*
			 * unknown reason to drop dead...
			 */
			Assert.assertTrue("2b) should be the same logical instance~ userA", this.userA.equals(aUsr001));
			Assert.assertTrue("2b) should be the same logical instance~ userB", this.userB.equals(aUsr002));
			this.sb.append(aUsr001).append("\r\n").append(aUsr002).append("\r\n\r\n");
			this.sb.append("userTheme of user001::").append(aUsr001.getUserTheme()).append("\r\n").
				append("userTheme of user002::").append(aUsr002.getUserTheme()).append("\r\n\r\n");
			
			/*
			 * 1) delete the User
			 */
			if (this.userA!=null) this.userDAO.deleteUser(userA);
			if (this.userB!=null) this.userDAO.deleteUser(userB);
			this.userAKey=null;
			this.userBKey=null;
			
			this.tx.flush();
			
		} catch(RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}
	}

	/**
	 * remove/change a User's userTheme; check if it works (since it is not n-to-n relationships; SHOULD work)
	 * 
	 * @author jason
	 * created at:: Aug 8, 2011  5:01:26 PM
	 */
	@Test
	public void doTest003() {
		UserTheme aTheme001=null;	// new
		UserTheme aTheme002=null;	// default
		User aUsr001=null;	// requery userA
		//Serializable aThemeKey=null;
		
		this.sb.append("\r\n************************************************\r\n").
		    append("*\tstart {UserThemeTestCase.doTest003}\t*\r\n").
			append("************************************************\r\n\r\n");
		
		try {
			/*
			 * 1) create User
			 */
			userA=new User("userA", "def", false, "hire", "a@abcAA.com", null);
			userB=new User("userB", "def", false, "hire", "a@abcBB.com", null);
			
			this.userAKey=this.userDAO.newUser(userA);
			this.userBKey=this.userDAO.newUser(userB);
			
			aTheme001=new UserTheme("themeDummy001", "dummy theme - to be deleted", "/tmp/template", null);
			this.userThemeDAO.newUserTheme(aTheme001);
			aTheme001.addUser(this.userA);
			this.userThemeDAO.updateUserTheme(aTheme001);
			
			/*
			 * 3) remove/change a User's userTheme; check if it works (since it is not n-to-n relationships; SHOULD work)
			 */
			this.sb.append("3a) remove/change a User's userTheme; check if it works (since it is not n-to-n relationships; SHOULD work)::\r\n\tQuery a User first :: ").
				append(this.userA).append("\r\n").append(this.userA.getUserTheme()).append("\r\n\r\n");
			this.sb.append("3b) change a User's userTheme to DEFAULT::\r\n\tsuccess? :: ");
			aTheme002=this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue());
			/*
			 * update association = delete + add~
			 */
			aTheme001.removeUser(this.userA);
			aTheme002.addUser(this.userA);
			//aUsr001.setUserTheme(aUTheme001);
			/*aUsr001.getUserTheme().removeUser(aUsr001);
			aUTheme001.addUser(aUsr001);*/
			/*
			 * Update the owner side should be done...
			 */
			/*this.userDAO.updateUser(aUsr001);
			this.userThemeDAO.updateUserTheme(aUTheme001);*/
			this.userThemeDAO.updateUserTheme(aTheme002);
			this.sb.append(true).append("\r\n\r\n");
			
			this.sb.append("3c) re-query~ should have a UserTheme pointing to the DEFAULT~::\r\n\tuserTheme = ???? :: ");
			aUsr001=this.userDAO.getUserByKey((Integer) this.userAKey);
			Assert.assertTrue("3c) the UserTheme's id should be equivalent to the DEFAULT_USER_THEME~", aUsr001.getUserTheme().getId()==Constants.DEFAULT_USER_THEME.intValue());
			Assert.assertTrue("3c) the userA and usr001 should be logically SAME!", aUsr001.equals(this.userA));
			this.sb.append(aUsr001).append("\r\n").append(aUsr001.getUserTheme()).append("\r\n\r\n");
			
			/*
			 * 1) delete the User
			 */
			if (this.userA!=null) this.userDAO.deleteUser(userA);
			if (this.userB!=null) this.userDAO.deleteUser(userB);
			this.userAKey=null;
			this.userBKey=null;
			
			this.tx.flush();
			
		} catch(RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}
	}
	
	/**
	 * remove/change a UserTheme's user(s), kick 1 User out etc; check if it works (since it is not n-to-n relationships; SHOULD work)
	 * 
	 * @author jason
	 * created at:: Aug 8, 2011  5:01:26 PM
	 */
	@Test
	public void doTest004() {
		UserTheme aTheme001=null;
		User aUsr001=null;
		Serializable aTheme001Key=null;
		
		this.sb.append("\r\n************************************************\r\n").
		    append("*\tstart {UserThemeTestCase.doTest004}\t*\r\n").
			append("************************************************\r\n\r\n");
		
		try {
			/*
			 * 1) create User
			 */
			userA=new User("userA", "def", false, "hire", "a@abcAA.com", null);
			userB=new User("userB", "def", false, "hire", "a@abcBB.com", null);
			
			this.userAKey=this.userDAO.newUser(userA);
			this.userBKey=this.userDAO.newUser(userB);
			
			aTheme001=new UserTheme("themeDummy001", "dummy theme - to be deleted", "/tmp/template", null);
			aTheme001Key=this.userThemeDAO.newUserTheme(aTheme001);
			aTheme001.addUser(this.userA);
			aTheme001.addUser(this.userB);
			this.userThemeDAO.updateUserTheme(aTheme001);
			
			/*
			 * 4) remove/change a UserTheme's user(s), kick 1 User out etc; check if it works (since it is not n-to-n relationships; SHOULD work) 
			 */
			this.sb.append("4a) remove/change a UserTheme's user(s), kick 1 User out etc; check if it works (since it is not n-to-n relationships; SHOULD work)::\r\n\tQuery the UserTheme first~::");
			aTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aTheme001Key);
			Assert.assertTrue("4a) should have 2 Users attached to this new UserTheme~", aTheme001.getUsers().size()==2);
			this.sb.append(aTheme001).append("\r\n").append(aTheme001.getUsers()).append("\r\n\r\n");
			
			if (aTheme001.getUsers().size()>0) {
				this.sb.append("4b) remove the 1st User from the Set and update it :: success ?? ");
				/*
				 * use association method...
				 */
				aTheme001.removeUser(this.userA);
				this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue()).addUser(this.userA);
				/*aUsr001=aUTheme001.getUsers().iterator().next();
				aUTheme001.removeUser(aUsr001);
				aUsr001.setUserTheme(this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue()));*/
				//aUTheme001.getUsers().remove(aUTheme001.getUsers().iterator().next());
				this.userThemeDAO.updateUserTheme(aTheme001);
				//this.userDAO.updateUser(aUsr001);
				this.sb.append(true).append("\r\n\r\n");
				
				this.sb.append("4c) re-query :: \r\n\t");
				aUsr001=this.userDAO.getUserByKey(this.userA.getId());
				Assert.assertTrue("4c) the User queried should have DEFAULT userTheme~", 
					aUsr001.getUserTheme().equals(this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue()))); 
				aTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aTheme001Key);
				Assert.assertTrue("4c) should have only 1 User LEFT!", aTheme001.getUsers().size()==1);
				this.sb.append(aUsr001).append("\r\n\t\t").append(aUsr001.getUserTheme()).append("\r\n\t").
					append(aTheme001).append("\r\n\t\t").append(aTheme001.getUsers()).append("\r\n\r\n");
			}			
			
			/*
			 * 1) delete the User
			 */
			if (this.userA!=null) this.userDAO.deleteUser(userA);
			if (this.userB!=null) this.userDAO.deleteUser(userB);
			this.userAKey=null;
			this.userBKey=null;
			
			this.tx.flush();
			
		} catch(RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}
	}
	
	/**
	 * add new user to a new UserTheme... perform delete on either side; check the cascade delete problem
	 * 
	 * @author jason
	 * created at:: Aug 8, 2011  5:01:26 PM
	 */
	@Test
	public void doTest005() {
		UserTheme aTheme001=null;
		User aUsr001=null;
		User aUsr002=null;
		Serializable aTheme001Key=null;
		
		this.sb.append("\r\n************************************************\r\n").
		    append("*\tstart {UserThemeTestCase.doTest005}\t*\r\n").
			append("************************************************\r\n\r\n");
		
		try {
			/*
			 * 1) create User
			 */
			userA=new User("userA", "def", false, "hire", "a@abcAA.com", null);
			userB=new User("userB", "def", false, "hire", "a@abcBB.com", null);
			
			this.userAKey=this.userDAO.newUser(userA);
			this.userBKey=this.userDAO.newUser(userB);
			
			/*
			 * 5) add new user to a new UserTheme... perform delete on either side; check the cascade delete problem
			 */
			this.sb.append("5a) add new user to a new UserTheme... perform delete on either side; check the cascade delete problem\r\n\tNew User::");
			aTheme001=new UserTheme("themeDummy002", "dummy theme - to be deleted", "/tmp/template", null);
			aTheme001Key=this.userThemeDAO.newUserTheme(aTheme001);
			
			/*
			 * use association methods; don't directly use setter...
			 */
			aTheme001.addUser(this.userA);
			aTheme001.addUser(this.userB);
			
			// re-query
			aUsr001=this.userDAO.getUserByKey((Integer) this.userAKey);
			aUsr002=this.userDAO.getUserByKey((Integer) this.userBKey);
			this.sb.append(aUsr001).append("\r\n\t").append(aUsr001.getUserTheme()).append("\r\nAnother User::");
			this.sb.append(aUsr002).append("\r\n\t").append(aUsr002.getUserTheme()).append("\r\nNew UserTheme::\r\n\t");
			
			// re-query
			aTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aTheme001Key);
			this.sb.append(aTheme001).append("\r\n\t").append(aTheme001.getUsers()).append("\r\n\r\n");
			
			/*
			 * don't directly delete an entity without using association methods... 
			 * unexpected results WILL occur~~~~
			 * 
			this.sb.append("5b) delete the User directly without using association methods~ ::\r\n\t");
			this.userDAO.deleteUser(aUsr002);
			// re-query
			aUsr002=this.userDAO.getUserByKey((Integer) aKey003);
			aUTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aKey002);
			this.sb.append("User after delete::").append(aUsr002).append("\r\n\tUserTheme after delete::").append(aUTheme001).append(" :: ").append(aUTheme001.getUsers()).append("\r\n\r\n");
			*/
			this.sb.append("5b) delete the User Using association methods~ ::\r\n\t");
			/*
			 * a) remove the user from userTheme by association first
			 * b) update either end calling updateXXX()
			 * c) really call the UserDAO's removeUser method
			 */
			aTheme001.removeUser(this.userB);
			this.userThemeDAO.updateUserTheme(aTheme001);
			this.userDAO.deleteUser(this.userB);
			// re-query
			aUsr001=this.userDAO.getUserByKey((Integer) this.userAKey);
			aTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aTheme001Key);
			this.sb.append("User after delete::").append(aUsr001).
				append("\r\n\tUserTheme after delete::").append(aTheme001).
				append(" :: \r\n\t\t").append(aTheme001.getUsers()).append("\r\n\r\n");
			
			/*
			 * 1) delete the User
			 */
			if (this.userA!=null) this.userDAO.deleteUser(userA);
			if (this.userB!=null) this.userDAO.deleteUser(userB);
			this.userAKey=null;
			this.userBKey=null;
			
			this.tx.flush();
			
		} catch(RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}
	}
	
	/**
	 * the combined test(s); however, separate them for clarity 
	 * and more precise Assertion(s)
	 * 
	 * @author jason
	 * created at:: Aug 3, 2011  4:36:32 PM
	 * @deprecated
	 */
	//@Test
	public void doUserNUserThemeTest001() {
		User aUsr001=null;
		User aUsr002=null;
		UserTheme aUTheme001=null;
		UserTheme aUTheme002=null;
		Serializable aKey001=null;
		Serializable aKey002=null;
		Serializable aKey003=null;
		
		try {
			/*
			 * 1) get a valid UserTheme (eg. the default UserTheme -- which is a MUST valid entry)
			 */
			this.sb.append("\r\n************************************************\r\n").
			    append("*\tstart {doUserNUserThemeTest001}\t*\r\n").
				append("************************************************\r\n\r\n");
			this.sb.append("1a) get a valid UserTheme (eg. the default UserTheme -- which is a MUST valid entry)::\r\n\tExisting Id::").append(Constants.DEFAULT_USER_THEME).append("::");
			
			aUTheme001=this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue());
			Assert.assertNotNull("1a) Default UserTheme should be AVAILABLE~~~", aUTheme001);
			this.sb.append(aUTheme001).append("\r\n\r\n");
			
			/*
			 * 2) add a new User and a new UserTheme (ordering of creation is UserTheme first, then User); associate them together
			 */
			this.sb.append("2a) add a new User and a new UserTheme (ordering of creation is UserTheme first, then User); associate them together::\r\n\tCreating a new UserTheme::");
			aUTheme002=new UserTheme("themeDummy001", "dummy theme - to be deleted", "/tmp/template", null);
			aKey001=this.userThemeDAO.newUserTheme(aUTheme002);
			aKey003=aKey001;
			Assert.assertNotNull("2a) should be able to create a UserTheme~", aKey001);
			
			aKey002=aUTheme002.getId();
//this.tx.flush();
			
			// re-query
			aUTheme002=this.userThemeDAO.getUserThemeByKey((Integer) aKey001);
			Assert.assertNotNull("2a) re-query should return the JUST created UserTheme~", aUTheme002);
			Assert.assertEquals("2a) the Keys after re-query should be the same~", ((Integer) aKey001).intValue(), aUTheme002.getId());
			this.sb.append(aKey001).append("\r\n\r\n");
			
			this.sb.append("2b) creating new Users to associate with the JUST created userTheme ::\r\n\tCreating new Users::");
			aUsr001=new User("abc001", "def", false, "hire", "a@abc.com", null);
			aUsr002=new User("abc002", "def", false, "hire", "a@abc.com", null);
			//aUsr001.setUserTheme(aUTheme002);
			//aUsr002.setUserTheme(aUTheme002);
			/*
			 * use association methods instead of direct manipulations~~~
			 */
			aUTheme002.addUser(aUsr001);
			aUTheme002.addUser(aUsr002);
			aKey001=this.userDAO.newUser(aUsr001);
			aKey002=this.userDAO.newUser(aUsr002);
			/*
			 * update the UserTheme table...
			 */
			this.userThemeDAO.updateUserTheme(aUTheme002);
			// re-query
			aUsr001=this.userDAO.getUserByKey((Integer) aKey001);
			aUsr002=this.userDAO.getUserByKey((Integer) aKey002);
			Assert.assertTrue("2b) Should be...non \"0\"", aUsr001.getId()>0);
			Assert.assertTrue("2b) Should be...non \"0\"", aUsr002.getId()>0);
			this.sb.append(aUsr001).append("\r\n").append(aUsr002).append("\r\n\r\n");
			this.sb.append("userTheme of user001::").append(aUsr001.getUserTheme()).append("\r\n").
				append("userTheme of user002::").append(aUsr002.getUserTheme()).append("\r\n\r\n");
//this.tx.flush();
			/*
			 * 3) remove/change a User's userTheme; check if it works (since it is not n-to-n relationships; SHOULD work)
			 */
			this.sb.append("3a) remove/change a User's userTheme; check if it works (since it is not n-to-n relationships; SHOULD work)::\r\n\tQuery a User first :: ").
				append(aUsr001).append("\r\n").append(aUsr001.getUserTheme()).append("\r\n\r\n");
			this.sb.append("3b) change a User's userTheme to DEFAULT::\r\n\tsuccess? :: ");
			aUTheme001=this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue());
			/*
			 * update association = delete + add~
			 */
			//aUsr001.setUserTheme(aUTheme001);
			aUsr001.getUserTheme().removeUser(aUsr001);
			aUTheme001.addUser(aUsr001);
			/*
			 * update both User and UserTheme... quite troublesome though...
			 */
			this.userDAO.updateUser(aUsr001);
//this.userThemeDAO.updateUserTheme(aUTheme001);
			this.sb.append(true).append("\r\n\r\n");
			
			this.sb.append("3c) re-query~ should have a UserTheme pointing to the DEFAULT~::\r\n\tuserTheme = ???? :: ");
			aUsr001=this.userDAO.getUserByKey(aUsr001.getId());
			Assert.assertTrue("3c) the UserTheme's id should be equivalent to the DEFAULT_USER_THEME~", aUsr001.getUserTheme().getId()==Constants.DEFAULT_USER_THEME.intValue());
			this.sb.append(aUsr001).append("\r\n").append(aUsr001.getUserTheme()).append("\r\n\r\n");
			
			/*
			 * 4) remove/change a UserTheme's user(s), kick 1 User out etc; check if it works (since it is not n-to-n relationships; SHOULD work) 
			 */
			this.sb.append("4a) remove/change a UserTheme's user(s), kick 1 User out etc; check if it works (since it is not n-to-n relationships; SHOULD work)::\r\n\tQuery the UserTheme first~::");
			aUTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aKey003);
			this.sb.append(aUTheme001).append("\r\n").append(aUTheme001.getUsers()).append("\r\n\r\n");
			
			if (aUTheme001.getUsers().size()>0) {
				this.sb.append("4b) remove the 1st User from the Set and update it :: success ?? ");
				/*
				 * should use this method in the long run, instead of direct 
				 * manipulation of the Set
				 */
				aUsr001=aUTheme001.getUsers().iterator().next();
				aUTheme001.removeUser(aUsr001);
				aUsr001.setUserTheme(this.userThemeDAO.getUserThemeByKey(Constants.DEFAULT_USER_THEME.intValue()));
				//aUTheme001.getUsers().remove(aUTheme001.getUsers().iterator().next());
				this.userThemeDAO.updateUserTheme(aUTheme001);
//this.userDAO.updateUser(aUsr001);
				this.sb.append(true).append("\r\n\r\n");
				
				this.sb.append("4c) re-query :: \r\n\t");
				aUsr001=this.userDAO.getUserByKey(aUsr001.getId());
				aUTheme001=this.userThemeDAO.getUserThemeByKey(aUTheme001.getId());
				this.sb.append(aUsr001).append("\r\n\t\t").append(aUsr001.getUserTheme()).append("\r\n\t").
					append(aUTheme001).append("\r\n\t\t").append(aUTheme001.getUsers()).append("\r\n\r\n");
			}
			
			/*
			 * 5) add new user to a new UserTheme... perform delete on either side; check the cascade delete problem
			 */
			this.sb.append("5a) add new user to a new UserTheme... perform delete on either side; check the cascade delete problem\r\n\tNew User::");
			aUTheme001=new UserTheme("themeDummy002", "dummy theme - to be deleted", "/tmp/template", null);
			aKey002=this.userThemeDAO.newUserTheme(aUTheme001);
			
			aUsr001=new User("abc003", "def", false, "hire", "a@abc.com", null);
			aUsr002=new User("abc004", "def", false, "hire", "a@abc.com", null);
			/*
			 * use association methods; don't directly use setter...
			 */
			aUTheme001.addUser(aUsr001);
			aUTheme001.addUser(aUsr002);
			
			aKey001=this.userDAO.newUser(aUsr001);
			aKey003=this.userDAO.newUser(aUsr002);
			// re-query
			aUsr001=this.userDAO.getUserByKey((Integer) aKey001);
			aUsr002=this.userDAO.getUserByKey((Integer) aKey003);
			this.sb.append(aUsr001).append("\r\n\t").append(aUsr001.getUserTheme()).append("\r\nAnother User::");
			this.sb.append(aUsr002).append("\r\n\t").append(aUsr002.getUserTheme()).append("\r\nNew UserTheme::\r\n\t");
			
			// re-query
			aUTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aKey002);
			this.sb.append(aUTheme001).append("\r\n\t").append(aUTheme001.getUsers()).append("\r\n\r\n");
			
			/*
			 * don't directly delete an entity without using association methods... 
			 * unexpected results WILL occur~~~~
			 * 
			this.sb.append("5b) delete the User directly without using association methods~ ::\r\n\t");
			this.userDAO.deleteUser(aUsr002);
			// re-query
			aUsr002=this.userDAO.getUserByKey((Integer) aKey003);
			aUTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aKey002);
			this.sb.append("User after delete::").append(aUsr002).append("\r\n\tUserTheme after delete::").append(aUTheme001).append(" :: ").append(aUTheme001.getUsers()).append("\r\n\r\n");
			*/
			this.sb.append("5b) delete the User Using association methods~ ::\r\n\t");
			/*
			 * a) remove the user from userTheme by association first
			 * b) update either end calling updateXXX()
			 * c) really call the UserDAO's removeUser method
			 */
			aUTheme001.removeUser(aUsr001);
			this.userThemeDAO.updateUserTheme(aUTheme001);
			this.userDAO.deleteUser(aUsr001);
			// re-query
			aUsr001=this.userDAO.getUserByKey((Integer) aKey001);
			aUTheme001=this.userThemeDAO.getUserThemeByKey((Integer) aKey002);
			this.sb.append("User after delete::").append(aUsr001).
				append("\r\n\tUserTheme after delete::").append(aUTheme001).
				append(" :: \r\n\t\t").append(aUTheme001.getUsers()).append("\r\n\r\n");
			
			this.tx.flush();
			
		} catch(RuntimeException re) {
			this.sb.append("**************************************\r\n").
				append(re.toString()).
				append("\r\n**************************************\r\n");
			re.printStackTrace(System.out);
			throw re;
		}
	}
}
